﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpDemos
{
    class OverridingToString : IFormattable
    {
        public string Name { get; set; }

        public decimal Revenue { get; set; }

        public string ContactPhone { get; set; }

        public override string ToString()
        {
            return Name;
        }

        /// <summary>
        /// supported formats:
        /// substitute n for name.
        /// substitute r for revenue
        /// substitute p for contact phone.
        /// Combos are supported: nr, np, npr, etc
        /// "G" is general.
        /// </summary>
        /// <param name="format">format of string specified</param>
        /// <param name="formatProvider">Own format provided by caller</param>
        /// <returns>formatted string</returns>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (formatProvider != null)
            {
                ICustomFormatter fmt = formatProvider.GetFormat(this.GetType()) as ICustomFormatter;

                if (fmt != null)
                {
                    return fmt.Format(format, this, formatProvider);
                }
            }

            switch (format)
            {
                case "r":
                    return Revenue.ToString();
                case "p":
                    return ContactPhone;
                case "nr":
                    return string.Format("{0,20}, {1,10:C}", Name, Revenue);
                case "np":
                    return string.Format("{0,20}, {1,15}", Name, ContactPhone);
                case "pr":
                    return string.Format("{0,15}, {1,10:C}",
                    ContactPhone, Revenue);
                case "pn":
                    return string.Format("{0,15}, {1,20}",
                    ContactPhone, Name);
                case "rn":
                    return string.Format("{0,10:C}, {1,20}",
                    Revenue, Name);
                case "rp":
                    return string.Format("{0,10:C}, {1,20}",
                    Revenue, ContactPhone);
                case "nrp":
                    return string.Format("{0,20}, {1,10:C}, {2,15}",
                    Name, Revenue, ContactPhone);
                case "npr":
                    return string.Format("{0,20}, {1,15}, {2,10:C}",
                    Name, ContactPhone, Revenue);
                case "pnr":
                    return string.Format("{0,15}, {1,20}, {2,10:C}",
                    ContactPhone, Name, Revenue);
                case "prn":
                    return string.Format("{0,15}, {1,10:C}, {2,15}",
                    ContactPhone, Revenue, Name);
                case "rpn":
                    return string.Format("{0,10:C}, {1,15}, {2,20}",
                    Revenue, ContactPhone, Name);
                case "rnp":
                    return string.Format("{0,10:C}, {1,20}, {2,15}",
                    Revenue, Name, ContactPhone);
                case "n":
                case "G":
                default:
                    return Name;
            }
        }
    }

    class CustomFormatter : IFormatProvider
    {
        public object GetFormat(Type formatType)
        {
            if (formatType == typeof(ICustomFormatter))
            {
                return new CustomFormatProvider();
            }

            return null;
        }

        class CustomFormatProvider : ICustomFormatter
        {
            public string Format(string format, object arg, IFormatProvider formatProvider)
            {
                OverridingToString c = arg as OverridingToString;

                if (c == null)
                    return c.ToString();

                return string.Format("{0,50}, {1,15}, {2,10:C}", c.Name, c.ContactPhone, c.Revenue);
            }
        }
    }
}
